package com.ums.upos.service;

import android.os.RemoteException;

import com.nexgo.common.ByteUtils;
import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.card.mifare.AuthEntity;
import com.nexgo.oaf.apiv3.card.mifare.BlockEntity;
import com.nexgo.oaf.apiv3.card.mifare.M1CardOperTypeEnum;
import com.nexgo.oaf.apiv3.card.mifare.M1KeyTypeEnum;
import com.ums.upos.GlobalDataHolder;
import com.ums.upos.uapi.ServiceResult;
import com.ums.upos.uapi.card.mifare.M1CardHandler;
import com.ums.upos.uapi.card.mifare.M1CardOperType;
import com.ums.upos.uapi.card.mifare.M1KeyTypeConstrants;
import com.ums.upos.uapi.device.reader.icc.IccCardReader;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by liyang on 15-5-13.
 */
public class M1CardHandlerBinder extends M1CardHandler.Stub {
    private final String TAG = "M1CardHandlerService";
    private Logger log = LoggerFactory.getLogger(TAG);
    private com.nexgo.oaf.apiv3.card.mifare.M1CardHandler sdkM1CardHandler;
    private IccCardReader reader;

    M1CardHandlerBinder(IccCardReader reader) {
        this.reader = reader;
        log = LoggerFactory.getLogger(TAG);
        sdkM1CardHandler = GlobalDataHolder.getInstance().getDeviceEngine().getM1CardHandler();
    }

    //获得M1卡授权
    @Override
    public int authority(int keyType, int blkNo, byte[] pwd, byte[] serialNo) throws RemoteException {
        log.info("call authority");
        try {
            log.debug("keyType:" + keyType
                    + "\nserialNo:" + ByteUtils.byteArray2HexStringWithSpace(serialNo)
                    + "\nblkNo:" + blkNo
                    + "\npwd:" + ByteUtils.byteArray2HexStringWithSpace(pwd));

            if (keyType != M1KeyTypeConstrants.KEYTYPE_B && keyType != M1KeyTypeConstrants.KEYTYPE_A) {
                return ServiceResult.Param_In_Invalid;
            }
            if (blkNo >= 255) return ServiceResult.Fail;

            AuthEntity authEntity = new AuthEntity();
            authEntity.setKeyType(keyType == M1KeyTypeConstrants.KEYTYPE_A ? M1KeyTypeEnum.KEYTYPE_A : M1KeyTypeEnum.KEYTYPE_B);
            authEntity.setBlkNo(blkNo * 4);//入参blkNo为扇区号,底层要求入参是块号,然后认证的是块号所在的扇区,所以这里*4;
            authEntity.setPwd(pwd);
//            authEntity.setUid(ByteUtils.byteArray2HexString(serialNo));
//            authEntity.setUid(sdkM1CardHandler.readUid());
            authEntity.setUid(ByteUtils.asciiByteArray2String(serialNo));
            int result = sdkM1CardHandler.authority(authEntity);
            log.debug("authority result {},SdkResult.Success:{}", result,SdkResult.Success);
            if (result == SdkResult.Success) {
                return ServiceResult.Success;
            } else {
                return ServiceResult.M1Card_Verify_Err;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.M1Card_Verify_Err;
        }
    }

    //读块数据
    @Override
    public int readBlock(int blkNo, byte[] blkValue) throws RemoteException {
        log.debug("blkNo:" + blkNo);
        try {
            if (blkNo >= 255) return ServiceResult.Fail;

            BlockEntity blockEntity = new BlockEntity();
            blockEntity.setBlkNo(blkNo);
            int result = sdkM1CardHandler.readBlock(blockEntity);
            log.debug("readBlock result {}", result);
            if (result == SdkResult.Success) {
                byte[] data = blockEntity.getBlkData();
                System.arraycopy(data, 0, blkValue, 0, Math.min(data.length, blkValue.length));
                log.debug("blkValue:{}", ByteUtils.byteArray2HexStringWithSpace(blkValue));
                return ServiceResult.Success;
            } else {
                return ServiceResult.Fail;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.Fail;
        }
    }

    //写块数据
    @Override
    public int writeBlock(int blkNo, byte[] blkValue) throws RemoteException {
        log.debug("blkNo:" + blkNo
                + "\nblkValue:" + ByteUtils.byteArray2HexStringWithSpace(blkValue));
        try {

            if (blkNo >= 255) return ServiceResult.Fail;
            BlockEntity blockEntity = new BlockEntity();
            blockEntity.setBlkNo(blkNo);
            blockEntity.setBlkData(blkValue);
            int result = sdkM1CardHandler.writeBlock(blockEntity);
            log.debug("writeBlock result {}", result);
            if (result == SdkResult.Success) {
                return ServiceResult.Success;
            } else {
                return ServiceResult.Fail;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.Fail;
        }
    }

    private int byteToInt(byte[] data) {
        int temp = 0;
        temp += ((data[0] << 0) & 0x000000ff);
        temp += ((data[1] << 8) & 0x0000ff00);
        temp += ((data[2] << 16) & 0x00ff0000);
        temp += ((data[3] << 24) & 0xff000000);
        return temp;
    }

    //对指定数据块进行充/减值/备份操作，将操作后的值更新到另一指定的数据块
    @Override
    public int operateBlock(int operType, int blkNo, byte[] value, int updBlkNo) throws RemoteException {
        log.debug("operType:" + operType
                + "\nblkNo:" + blkNo
                + "\nvalue:" + ByteUtils.byteArray2HexStringWithSpace(value)
                + "\nupdBlkNo:" + updBlkNo);
        try {
            if (blkNo >= 255) return ServiceResult.Fail;

            if (operType != M1CardOperType.BACKUP && operType != M1CardOperType.DECREMENT
                    && operType != M1CardOperType.INCREMENT)
                return ServiceResult.M1Card_Card_OperType_Error;
            int result = 0;
            BlockEntity blockEntity = new BlockEntity();
            blockEntity.setBlkNo(blkNo);
            blockEntity.setDesBlkNo(updBlkNo);
            blockEntity.setBlkValue(byteToInt(value));
            if (operType == M1CardOperType.INCREMENT) {
                blockEntity.setOperType(M1CardOperTypeEnum.INCREMENT);
            } else if (operType == M1CardOperType.DECREMENT) {
                blockEntity.setOperType(M1CardOperTypeEnum.DECREMENT);
            } else {
                blockEntity.setOperType(M1CardOperTypeEnum.BACKUP);
            }
            result = sdkM1CardHandler.operateBlock(blockEntity);
            if (result == SdkResult.Success) {
                return ServiceResult.Success;
            } else {
                return ServiceResult.Fail;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.Fail;
        }
    }
}

